home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d20 / dorskel2.arc / DOORSKEL.C < prev    next >
C/C++ Source or Header  |  1991-12-05  |  27KB  |  1,005 lines

  1. /**********************************************/
  2. /*                                              */
  3. /* XBBS Door Skeleton -- TC 2.0/MSC 6.0a code */
  4. /* Copyright (c) 1990/91 by M. Kimes          */
  5. /* All Rights Reserved                        */
  6. /* May be freely used for >>>FREE<<< programs */
  7. /* as long as you don't try to save any souls */
  8. /* (nasty habit)                              */
  9. /*                                            */
  10. /**********************************************/
  11.  
  12. /* Always include this module (with appropriate #defines) */
  13.  
  14. /**************************************************************************
  15.   Miscellaneous notes:
  16.  
  17.     #define XBBS and the program will be compiled to read ONLINE.XBS
  18.     #define DORINFO and the program will be compiled to read DORINFO?.DEF
  19.     #define both and first ONLINE.XBS will be read, then DORINFO?.DEF
  20.     (don't know why you'd wanna do that)
  21.     #define neither and all info must come from command line
  22.     #define FINDUSER and a routine to find a given user (by name) will
  23.             be compiled in (finduser()) for XBBS' USERS.BBS
  24.     #define NOREADFILE and the file reader routine (readtext()) will NOT
  25.             be compiled
  26.     #define DISABLEBREAK to disable CTRL-BREAK/CTRL-C
  27.     #define DIALTRANS to include a dial_trans function for modem dialing,
  28.             etc.
  29.  
  30.     set chars to be unsigned by default
  31.     recommend large model (recompile screen2.asm and ansi.asm if other)
  32.     this code requires a FOSSIL for serial i/o--see function fossil()
  33.  
  34.     My indenting style is thanks to Mike Looney who taught me everything
  35.     he knows.  ;^D
  36. ***************************************************************************/
  37.  
  38. #include "doorskel.h"   /* DOORSKEL's include file */
  39.  
  40.  
  41. /* Conditional global variables created here */
  42.  
  43. #ifdef XBBS
  44.     struct _config conf;
  45.     struct _user   user;
  46.     word           userno;
  47.     struct time    timeon;
  48.     char           timer_off;
  49.     word           hold_time;
  50.     char           age;
  51.     char           pages;
  52.     struct _mboard mboard;
  53.     struct _fboard fboard;
  54.     struct _events event[10];
  55.     char           variable[10][82];
  56.     ulong           starter;
  57. #endif
  58.  
  59.  
  60. /* Global variables created here -- NOTE DEFAULTS! */
  61.  
  62. char   debug_mode       = 0;
  63. char   graphics         = 0;
  64. time_t timelimit;
  65. word   baud             = 0;
  66. char   numlines         = 24;
  67. word   seclvl           = 5;
  68. time_t startt           = 0;
  69. char   sysopin          = 0;
  70. char   fastANSI         = 1;
  71. char   commport         = 0;
  72. char   logfile[133]     = "XBBS.LOG";
  73. char   username[36]     = "A. Ghost";
  74. char   width            = 80;
  75. char   chatting         = 0;
  76. char   chatted          = 0;
  77. char   nodenumber       = 1;
  78. char   system_name[64]  = "";
  79. char   sysop[36]        = "";
  80.  
  81. /* These are tied to the screen2.asm module */
  82.  
  83. int    maxx,maxy;           /* size of local screen */
  84. word   videomethod,vbase;
  85. char   current_color = 7,cls_clr = 7;
  86.  
  87. int FAR *vseg;      /* this one we use for internal dputs() replacement */
  88.  
  89. #ifdef __TURBOC__
  90.     extern unsigned _Cdecl _stklen = 8192; /* Stack length; adjust if req'd */
  91.                                            /* note MSC adjusts stack at compile or link time */
  92. #endif
  93.  
  94.  
  95.  
  96.  
  97.  
  98. void _cdecl main (int argc,char **argv) {
  99.  
  100.     register int x;
  101.     char         *p;
  102.  
  103.  
  104.   set_mtask();  /* see mtask.c */
  105.  
  106.   /* Please leave this next line in as a courtesy...thanks */
  107.   fputs(
  108.       "\x1b[2J\x1b[0;2;37m\x1b[1;1H\r\04 Built from M. Kimes' DOORSKEL kit v1.03.\n",
  109.       stdout);
  110.  
  111.   srand((unsigned)time(NULL));
  112.   videomethod = 0;                      /* default direct video */
  113.   vbase = (vmode() == 7 ? 0xb000: 0xb800);  /* find base address of video ram */
  114.   vseg = MK_FP(vbase,0);                /* address of video ram as pointer */
  115.   timelimit = time(NULL) + (30L * 60L); /* default 30 min timelimit */
  116.   set_screen_size();                    /* find screen size */
  117.   setcoords(0,0,maxx - 1,maxy - 2);     /* change if you want more than one */
  118.                                         /* status line or whatever */
  119.  
  120. #ifdef DISABLEBREAK
  121.   break_handler(0);
  122. #endif
  123.  
  124.   if (argc == 2 && !stricmp(argv[1],"H")) {     /* check for help request */
  125.     printinfo();                                /* FILENAME H on command line */
  126.     printhelp();
  127.     exit(0);
  128.   }
  129.  
  130.   set_raw();                                    /* for output speed */
  131.  
  132.   atexit(deinitialize);
  133.  
  134.   /* read exit files per conditional compilation */
  135.  
  136. #ifdef XBBS
  137.     readconfig();
  138.     getonline();
  139. #endif
  140.  
  141. #ifdef DORINFO
  142.     readinfo();
  143. #endif
  144.  
  145.   for (x = 1;x < argc;x++) {    /* process command line args */
  146.  
  147. ReSwitch:
  148.  
  149.     switch (toupper(*argv[x])) {
  150.         case '-':   /* ignore common "switch" chars */
  151.         case '/':   memmove(argv[x],&argv[x][1],strlen(argv[x]));
  152.                     goto ReSwitch;
  153.  
  154.         case 'F':   fastANSI = 0;   /* turn INT 29H fastwriting off */
  155.                     break;
  156.  
  157.         case 'U':   strncpy(username,&argv[x][1],36);   /* user's name */
  158.                     username[35] = 0;
  159.                     break;
  160.  
  161.         case 'N':   nodenumber = (char)atoi(&argv[x][1]);   /* node number */
  162.                     break;
  163.  
  164.         case 'L':   numlines = (char)atoi(&argv[x][1]); /* length of user's screen */
  165.                     break;
  166.  
  167.         case 'W':   width = (char)atoi(&argv[x][1]);    /* width of user's screen */
  168.                     break;
  169.  
  170.         case 'B':   baud = (word)atoi(&argv[x][1]);     /* current baud rate */
  171.                     break;                              /* 0 = local only    */
  172.  
  173.         case 'G':   if(atoi(&argv[x][1])) graphics = 1; /* ANSI on if non-zero */
  174.                     break;
  175.  
  176.         case 'C':   commport = (char)atoi(&argv[x][1]); /* 0 = COM1 */
  177.                     break;
  178.  
  179.         case 'S':   seclvl = atoi(&argv[x][1]);         /* security level */
  180.                     break;
  181.  
  182.         case 'T':   timelimit = time(NULL) + ((atol(&argv[x][1])) * 60L); /* time in minutes */
  183.                     break;
  184.  
  185.         case 'M':   videomethod = atoi(&argv[x][1]);  /* for direct screen write control; 0 = direct, 1 = bios */
  186.                     break;
  187.  
  188.         case '!':   debug_mode = 1;                   /* turn on debug printing */
  189.                     break;
  190.  
  191.         case 'X':   strcpy(logfile,&argv[x][1]);      /* set logfile */
  192.                     break;
  193.  
  194.         /********* add any special command switches here **********/
  195.         /********* remember to add help in printhelp() below ******/
  196.  
  197.         default:    fputs("\nUnknown argument `",stdout);
  198.                     fputs(argv[x],stdout);
  199.                     fputs("'\n",stdout);
  200.                     my_sleep(1);
  201.     }
  202.   }
  203.   setfastansi(fastANSI);
  204.   fossil(INIT,0);   /* activates FOSSIL driver */
  205.   cls();            /* clear our screen and theirs */
  206.  
  207.   printg("\x1b[0;1;37m");   /* default colors for ANSI users */
  208.   p = PROGRAM_NAME;         /* transmit program name */
  209.   if(baud) while (*p++) while(!fossil(TRANSMIT,*p)) carrchk();
  210.   printinfo();              /* print local program id info */
  211.   printm("\r\n");
  212.  
  213.   mainloop();       /* jumps to your "program" in DOORSKL4.C */
  214.  
  215. /*  If you want to change parameters in CONFIG.BBS or ONLINE.XBS,
  216.  *  change them, then call saveconfig() or prepare() here or in
  217.  *  deinitialize() (only for XBBS use)
  218.  */
  219.  
  220. }
  221.  
  222.  
  223.  
  224. void _fastcall printhelp (void) {  /* Print help screen--edit to taste
  225.                                       Add to as required */
  226.  
  227.     fputs(" Command line arguments:\n"
  228.           "L<screen lines>\n"
  229.           "N<nodenumber>\n"
  230.           "U<user name>\n"
  231.           "W<screen width>\n"
  232.           "T<time in minutes>\n"
  233.           "B<baudrate (0-38400...?)>\n"
  234.           "G<graphics (0 or 1)>\n"
  235.           "C<commport (0=COM1)>\n"
  236.           "S<security level>\n"
  237.           "M<mode (0=direct video, 1=BIOS, 2=DOS)>\n"
  238.           "X<filename> (Log File)\n"
  239.           "F (Fast ANSI writes (through INT 29H) off)\n"
  240.           "! (Debug mode on)\n",stdout);
  241.  
  242. #ifdef DORINFO
  243.     fputs(" Requires a DORINFO?.DEF file\n",stdout);
  244. #endif
  245.  
  246. #ifdef XBBS
  247.     fputs(" Requires XBBS ONLINE.XBS and CONFIG.BBS files\n",stdout);
  248. #endif
  249. }
  250.  
  251.  
  252.  
  253.  
  254. #ifdef DISABLEBREAK
  255.  
  256. void _cdecl break_handler (int sigl) {      /* guess */
  257.  
  258.   signal(SIGINT,SIG_IGN);
  259.   /* do whatever you want */
  260.   signal(SIGINT,break_handler);
  261.   return;
  262. }
  263.  
  264. #endif
  265.  
  266.  
  267.  
  268. void _fastcall chat (void) {   /* Cheap chat-mode */
  269.  
  270.     char a[3];
  271.     union REGS r;
  272.  
  273.  
  274.     printg("\x1b[0;1;33m");
  275.     printm("\r\n\r\nChat mode engaged\r\n\r\n");
  276.     while (chatting) {
  277.        *a = inkey();
  278.        a[1] = 0;
  279.        if (chatting) {
  280. #ifdef __TURBOC__
  281.          _AH = 3;
  282.          _BH = 0;
  283.          geninterrupt(16);
  284. #else
  285.          r.h.ah = 3;
  286.          r.h.bh = 0;
  287.          int86(16,&r,&r);
  288. #endif
  289.          if (*a == '\r') printm("\r\n");
  290. #ifdef __TURBOC__
  291.          if ((*a == '\r') || (*a == ' ' && _DL > maxx - 10)) printm("\r\n");
  292. #else
  293.          if((*a == '\r') || (*a == ' ' && r.h.dl > maxx - 10)) printm("\r\n");
  294. #endif
  295.          else printm(a);
  296.        }
  297.     }
  298.     printm("\r\n\r\nChat mode ended\r\n\r\n");
  299.     chatted++;
  300. }
  301.  
  302.  
  303.  
  304. void _fastcall printg (char *text) {  /* Print only if user has graphics set */
  305.  
  306.     if(graphics) printm(text);
  307. }
  308.  
  309.  
  310.  
  311. char _fastcall inkey (void) {       /* like BASIC's INKEY$ local and remote */
  312.  
  313.     char arg = 0;
  314.     union REGS rg;
  315.  
  316.  
  317.     rg.h.ah = 11;
  318.     int86(0x21,&rg,&rg);    /* check DOS for key waiting */
  319.     if (rg.h.al) {          /* key is waiting */
  320.         rg.h.ah = 8;
  321.         int86(0x21,&rg,&rg);
  322.         if (rg.h.al) return((char)(rg.h.al));   /* got normal key */
  323.         rg.h.ah = 8;                            /* else got extended key */
  324.         int86(0x21,&rg,&rg);
  325.         arg = specialkey(rg.h.al);
  326.         if (arg) return (arg);      /* is a non-reserved extended key */
  327.     }
  328.  
  329.     if (baud) {
  330.       arg = carrchk();  /* check carrier and whether a key is available */
  331.       if (!(arg & 1)) return 0; /* no key available */
  332.       fossil(RECVWAIT,arg);
  333.       if(!arg || arg == '\x1b') return specialmod(arg); /* ANSI or Doorway key else normal key */
  334.       return arg;
  335.     }
  336.  
  337.     getxbbstime();  /* check timeleft, update status line */
  338.  
  339.     pause_mtask();  /* give up timeslice */
  340.     return 0;       /* return "no key" */
  341. }
  342.  
  343.  
  344.  
  345. char _fastcall specialmod (char wuz) {
  346.  
  347.     /* process "extended" keys and ANSI cursor keys */
  348.  
  349.     char arg;
  350.     clock_t t1;
  351.  
  352.  
  353.       t1 = timerset(250L);
  354.       while(!timeup(t1)) {
  355.           arg = carrchk();
  356.           if (arg & 1) break;       /* 1/4 sec for next part of key sequence */
  357.       }
  358.  
  359.       if (!(arg & 1)) return 0;
  360.       arg = (fossil(RECVWAIT,arg));
  361.       if(!wuz) return (arg | 128);  /* "Doorway" key */
  362.       if (arg != '[') return 0;     /* it's a bad ANSI sequence */
  363.  
  364.       t1 = timerset(250L);          /* we have <-[ so far... */
  365.       while(!timeup(t1)) {
  366.           arg = carrchk();
  367.           if(arg & 1) break;
  368.       }
  369.  
  370.       arg = carrchk();
  371.       if(!(arg & 1)) return 0;
  372.       arg = (fossil(RECVWAIT,arg));
  373.       if((arg != '1') && (arg != 'A') && (arg != 'B') &&
  374.           (arg != 'C') && (arg != 'D') && (arg != 'K'))
  375.           return 0;   /* not an ANSI sequence we recognize */
  376.  
  377.       /* note internal representation of cursor keys */
  378.  
  379.       if(arg == 'A') return 1;   /* UP    */
  380.       if(arg == 'B') return 2;   /* DOWN  */
  381.       if(arg == 'C') return 3;   /* RIGHT */
  382.       if(arg == 'D') return 4;   /* LEFT  */
  383.       if(arg == 'K') return 211; /* DELETE */
  384.  
  385.       /* some terms send <-[1A, some just send <-[A; this checks former */
  386.  
  387.       t1 = timerset(250L);
  388.       while(!timeup(t1)) {
  389.           arg = carrchk();
  390.           if (arg & 1) break;
  391.       }
  392.  
  393.       arg = carrchk();
  394.       if(!(arg & 1)) return 0;
  395.       arg = (fossil(RECVWAIT,arg));
  396.       if((arg != 'A') && (arg != 'B') && (arg != 'C') &&
  397.          (arg != 'D')) return 0;
  398.       if(arg == 'A') return 1;
  399.       if(arg == 'B') return 2;
  400.       if(arg == 'C') return 3;
  401.       if(arg == 'D') return 4;
  402.  
  403.       return 0;
  404. }
  405.  
  406.  
  407.  
  408.  
  409. char _fastcall specialkey (char a) {
  410.  
  411.    /* this function processes extended local keys.  add your own... */
  412.    /* a is second half of scan code (0 + a) */
  413.  
  414.   switch (a) {
  415.  
  416.     case 45:cls();          /* ALT-Q for example, 0 + 45 */
  417.             exit(0);        /* QUIT DOOR */
  418.  
  419.     case 35:                /* HANG UP */
  420.             fossil(DTR,DOWN);
  421.             exit(1);
  422.  
  423.     case 46:                /* chat mode */
  424.             chatting = 1 - chatting;
  425.             if(chatting) chat();
  426.             return 0;
  427.  
  428.     case 36:                /* SysOp SHELL */
  429.             cls();
  430.             printm(" \x1b[0m\r\nThe SysOp has jumped to DOS...please wait...\r\n");
  431.             fossil(FLUSHOUT,0);
  432.             pause_mtask();
  433.             spawnit(getenv("COMSPEC"));
  434.             printm("\r\nThe SysOp has returned...please continue...\r\n");
  435.             my_sleep(1);
  436.             return(0);
  437.  
  438.     case 131:             /* MORE TIME... ALT + */
  439.             timelimit += 60L;
  440.             return 0;
  441.  
  442.     case 130:             /* LESS TIME... ALT - */
  443.             if (timelimit - getxbbstime() < 60L) timelimit = time(NULL);
  444.             else timelimit -= 60L;
  445.             return 0;
  446.  
  447.   }
  448.  
  449.   return (a | 128);       /* return "extended key" */
  450. }
  451.  
  452.  
  453.  
  454.  
  455. void _fastcall cls (void) {             /* like BASIC's CLS */
  456.  
  457.     char *clr_string = "\x1b[0m\x1b[2J";
  458.  
  459.  
  460.     /* first clear remote */
  461.  
  462.     if(!graphics) clr_string = "\xc";
  463.     if(baud) {
  464.         while (*clr_string++) {
  465.             while(!fossil(TRANSMIT,*clr_string)) carrchk();
  466.         }
  467.     }
  468.  
  469.     /* then clear local */
  470.  
  471.     fputs("\x1b[0m\x1b[2J",stdout);
  472.     print_stat();   /* replace erased status line */
  473. }
  474.  
  475.  
  476.  
  477. char _fastcall fossil (char function,char arg) {
  478.  
  479.     /* handles most common fossil calls */
  480.     /* see FOSSIL.DOC or FSC-0015 for more info on FOSSIL drivers */
  481.  
  482.     union REGS rg;
  483.  
  484.  
  485.     if(!baud) return 0;
  486.     if (function == FLUSHOUT) {
  487.        do {
  488.            carrchk();
  489.            rg.h.ah = 3;
  490.            rg.x.dx = commport;
  491.            int86(20,&rg,&rg);
  492.        } while (!(rg.h.ah & 64));
  493.        return(0);
  494.     }
  495.  
  496.     if (function == WATCHDOG) rg.h.al = arg;
  497.     else if (function == DTR) rg.h.al = arg;
  498.     else if (function == TRANSWAIT) rg.h.al = arg;
  499.     else if (function == TRANSMIT) rg.h.al = arg;
  500.     else if (function == ONOFF) rg.h.al = arg;
  501.  
  502.     rg.x.dx = commport;
  503.     rg.h.ah = function;
  504.     int86(20,&rg,&rg);
  505.  
  506.     if (function == INIT) {
  507.        if (rg.x.ax != INITOK) { /* ARGH!  couldn't initialize FOSSIL */
  508.            fputs("\nFossil not responding...RTFM.\n",stdout);
  509.            exit (3);
  510.        }
  511.        return (0);
  512.     }
  513.  
  514.     if (function == GETSTAT) {
  515.        arg = rg.h.ah;
  516.        if (rg.h.al & 128) {
  517.            arg |= 128;
  518.            return (arg);
  519.        }
  520.        arg &= 127;
  521.        return (arg);
  522.     }
  523.  
  524.     if (function == RECVWAIT) return rg.h.al;
  525.     if (function == TRANSMIT) return (char)rg.x.ax;
  526.  
  527.     return (0);
  528. }
  529.  
  530.  
  531.  
  532. void _cdecl deinitialize (void) {    /* deinit fossil, etc. at exit */
  533.  
  534.     fossil(FLUSHOUT,0);
  535.     fossil (DEINIT,0);
  536.  
  537.     fcloseall();
  538.  
  539.     set_cooked();
  540.  
  541.     /* put other atexit stuff you need here... */
  542.  
  543.     printm("\r\n");
  544.     fputs("\x1b[0;2;37m\n",stdout);
  545. }
  546.  
  547.  
  548.  
  549. /* generic input routine -- see types in doorskel.h */
  550.  
  551. char * _fastcall genin (char length,    /* maximum length of user input */
  552.                         char password,  /* "shroud" input echo if non-zero */
  553.                         char caps,      /* force input to uppercase if non-zero */
  554.                         char hot,       /* "hot" input if non-zero */
  555.                         char type) {    /* type of input -- see doorskel.h */
  556.  
  557. static char input[257];
  558. int x = 0;
  559. char one = 0;
  560. char randchr[2];
  561.  
  562.  
  563.  length--;  /* note */
  564.  
  565. AfterChat:
  566.  
  567.  strset(input,0);
  568.  startt = getxbbstime();
  569.  
  570.  while ((getxbbstime() - startt) < 241 || (chatted != 0)) {
  571.  
  572.   one = inkey();
  573.   if (one == '\r') break;
  574.  
  575. Nogo:
  576.  
  577.   if (one == 8) {
  578.       if (x > 0) {
  579.          printm(BACKSPACE);
  580.          input [--x]=0;
  581.          if ((type==PHONE) && ((x==2) || (x==5))) printm(BACKSPACE);
  582.          if ((type==DATE) && ((x==3) || (x==5))) printm(BACKSPACE);
  583.       }
  584.       continue;
  585.   }
  586.   if (type==ARROWS) {
  587.     switch (one) {
  588.         case 1:
  589.         case 2:
  590.         case 3:
  591.         case 4:
  592.         case 5:
  593.         case '?':
  594.         case 27:
  595.         case 11:    *input=one;
  596.                     return (input);
  597.         case 13:    *input=0;
  598.                     return (input);
  599.     }
  600.     if (isprint(one)) {
  601.         *input=toupper(one);
  602.         return (input);
  603.     }
  604.     continue;
  605.   }
  606.  
  607.   if ((caps) || (type==YESNO) || (type==YESNOM) || (type==FLE) || (type==FLEW) || (type==FLEPW) || (type==FLEP) || (type==FLENX)) one=toupper(one);
  608.   if (x <= length) {
  609.       if(type==HYPER && (one==27 || one==11)) goto BreakOutOfIt;
  610.       if(type==HYPER && graphics && one<6 && one!=3) goto BreakOutOfIt;
  611.       if (type==NAME) {
  612.         if((isalpha(one)==0) && (one!=' ') && (one!='.') && (one!='-') || (x==0 && one==' ')) continue;
  613.         if ((one==' ') && (strchr(input,' ')!=NULL)) continue;
  614.       }
  615.       if (type==NEAT) {
  616.         if((isalnum(one)==0) && (one!=' ') || (x==0 && one==' ')) continue;
  617.       }
  618.       if ((type==NEAT) || (type==NAME)) {
  619.         if(x==0) {
  620.             one=toupper(one);
  621.         }
  622.         else one=tolower(one);
  623.       }
  624.       if((type==NEAT) || (type==NAME)) {
  625.         if((x>0) && ((input[x-1]==' ') || (input[x-1]=='.') || (input[x-1]=='-'))) one=toupper(one);
  626.       }
  627.       if ((type==SUBJECT) && (x==0)) one=toupper(one);
  628.       if ((type==SUBJECT) && (isprint(one)==0)) continue;
  629.       if ((type==ALLL) && (isprint(one)==0)) continue;
  630.       if ((type==ALLL) && (one==127)) one=8;
  631.       if ((type==ALPHA) && (isalpha(one)==0) && (one!=' ')) continue;
  632.       if (((type==NUM) || (type==PHONE) || (type==DATE)) && (isdigit(one)==0)) continue;
  633.       if ((type==ALPHANUM) && (isalnum(one)==0) && (one!=' ')) continue;
  634.       if (((type==YESNO) || (type==YESNOM)) && (one!='Y' && one!='N')) continue;
  635.       if (type==FLE) {
  636.          if ((isalnum(one)==0) && (!strchr("._-+=!@#$%^&/",one))) continue;
  637.       }
  638.       if (type==FLENX) {
  639.          if ((isalnum(one)==0) && (!strchr("_-+=!@#$%^&/",one))) continue;
  640.       }
  641.       if (type==FLEP) {
  642.          if ((isalnum(one)==0) && (!strchr("._-+=!@#$%^&/\\:",one))) continue;
  643.       }
  644.       if (type==FLEW) {
  645.           if ((isalnum(one)==0) && (!strchr("._-+=!@#$%^&/?*",one))) continue;
  646.       }
  647.       if (type==FLEPW) {
  648.         if ((isalnum(one)==0) && (!strchr("._-+=!@#$%^&/?*\\:",one))) continue;
  649.       }
  650.       if ((type==FLE) || (type==FLEP) || (type==FLEW) || (type==FLEPW)) {
  651.          if ((one=='.') && (strchr(input,'.')!=NULL)) continue;
  652.       }
  653. BreakOutOfIt:
  654. ;
  655.    }
  656.    if (chatted > 0) {   /* allow for chat having interrupted us */
  657.     chatted = 0;
  658.     goto AfterChat;
  659.    }
  660.    if ((one!=0) && (x <= length)) {
  661.       input[x]=one;
  662.       input[++x]=0;
  663.       if (type==YESNOM) {
  664.                         return(input);
  665.       }
  666.       if (password == 0) printm(&input[x - 1]);
  667.       if (password != 0) {
  668.         randchr[0] = (rand() % 10) + 33;
  669.         randchr[1] = 0;
  670.         printm(randchr);
  671.       }
  672.       if ((type == PHONE) && ((x == 3) || (x == 6))) printm("-");
  673.       if ((type == DATE) && ((x == 4) || (x == 6))) printm("/");
  674. AfterCtrl:
  675.       if ((hot != 0)&&(x >= length)) {
  676.             return (input);
  677.       }
  678.       startt = getxbbstime();
  679.    }
  680.  
  681.   }
  682.   if (chatted) {
  683.     chatted=0;
  684.     goto AfterChat;
  685.   }
  686.   if ((getxbbstime() - startt) > 240) {
  687.       fputs("\nUser time-out...\n",stdout);
  688.       exit (2);
  689.   }
  690.   return (input);
  691. }
  692.  
  693.  
  694.  
  695. char _fastcall carrchk (void) {  /* Checks for carrier */
  696.  
  697.     union REGS rg;
  698.  
  699.  
  700.     if (baud) {
  701.        rg.x.dx = commport;
  702.        rg.h.ah = GETSTAT;
  703.        int86(20,&rg,&rg);
  704.        if (!(rg.h.al & 128)) {  /* no carrier */
  705.            my_sleep(1);         /* delay a sec, try again */
  706.            rg.x.dx = commport;
  707.            rg.h.ah = GETSTAT;
  708.            int86(20,&rg,&rg);
  709.            if (!(rg.h.al & 128)) {  /* still no carrier, outta here */
  710.                fossil(DTR,DOWN);
  711.                baud=0;
  712.                fputs("\n\04 Lost carrier...\n",stdout);
  713.                exit (1);
  714.            }
  715.        }
  716.        return (rg.h.ah);    /* can be inspected to see if input char is ready */
  717.     }
  718.     return 0;
  719. }
  720.  
  721.  
  722. void _fastcall hitreturn (void) {    /* pause until [Enter] is pressed */
  723.  
  724.     register word x;
  725.  
  726.  
  727.     startt = getxbbstime();
  728.     printm("\r\n[Enter] to continue...");
  729.     while ((getxbbstime() - startt) < 241L) {
  730.         if (inkey() == '\r') goto HeDid;
  731.     }
  732.     fputs("\n\04User time-out...\n",stdout);    /* dump lazy bum */
  733.     exit (2);
  734.  
  735. HeDid:
  736.  
  737.     for(x = 0;x < 22;x++) printm(BACKSPACE);    /* Back over prompt */
  738. }
  739.  
  740.  
  741.  
  742. time_t _fastcall getxbbstime (void) {
  743.  
  744.     /* checks user time, updates mins remaining on status line, warns
  745.        user of impending out-of-time, etc.  returns current time_t */
  746.  
  747.     static time_t xbbs_time,lasttime;
  748.     static int warned = 0,x,y;
  749.  
  750.  
  751.     xbbs_time = time(NULL);
  752.  
  753.     if (timelimit < xbbs_time + 120L && !warned) {
  754.         warned++;
  755.         printfm("\x1b[s\x1b[%d;1H\x1b[K\x1b[0;1;37m",maxy - 2);
  756.         printfm("\07WARNING: %ld mins left!!!\x1b[u",(timelimit - xbbs_time) / 60L);
  757.         fossil(FLUSHOUT,0);
  758.     }
  759.  
  760.     if (timelimit > xbbs_time + 120L && warned) warned = 0;
  761.  
  762.     if (timelimit < xbbs_time) {
  763.         timelimit = xbbs_time + 240L;
  764.         printfm("\x1b[%d;1H\x1b[K\x1b[0;1;37mSorry, time to logoff...",maxy - 2);
  765.         fossil(FLUSHOUT,0);
  766.         exit(0);
  767.     }
  768.  
  769.     if(lasttime != xbbs_time) {
  770.         curr_cursor(&x,&y);
  771.         current_color = 7 * 16;
  772.         dprintf(maxx - 6,maxy,"%-5ld",(timelimit - xbbs_time) / 60L); /* note method of */
  773.         lasttime = time(NULL);                          /* determining time */
  774.         cursor(x,y);                                    /* remaining...     */
  775.     }
  776.  
  777.     return xbbs_time;
  778. }
  779.  
  780.  
  781.  
  782. void _fastcall printinfo (void) { /* Just prints prog info locally */
  783.  
  784.     fprintf(stderr,"  %s\n\04 %s\n\04 Compiled: %s  %s\n",PROGRAM_NAME,COPY_RIGHT,__DATE__,__TIME__);
  785. }
  786.  
  787.  
  788.  
  789. char * _fastcall fidodate (void) {  /* Builds a _correct_ Fido(tm) datestring */
  790.  
  791.     /* this is here because sooooo many people SCREW IT UP */
  792.     /* this is the RIGHT way to make a Fido date string */
  793.     /* see FTS-0001 for more info */
  794.  
  795.  #ifdef __TURBOC__
  796.  
  797.     char months[12][4]={    /* note; newer versions of TC have strftime... */
  798.        "Jan",
  799.        "Feb",
  800.        "Mar",
  801.        "Apr",
  802.        "May",
  803.        "Jun",
  804.        "Jul",
  805.        "Aug",
  806.        "Sep",
  807.        "Oct",
  808.        "Nov",
  809.        "Dec"
  810.     };
  811.     static char fdate[20];
  812.     struct date dos_date;
  813.     struct time dos_time;
  814.  
  815.    /* 26 Jul 89  06:23:47 */
  816.  
  817.     getdate(&dos_date);
  818.     gettime(&dos_time);
  819.  
  820.     sprintf(fdate,"%02hu %s %02d  %02hu:%02hu:%02hu",dos_date.da_day,months[dos_date.da_mon-1],dos_date.da_year%100,dos_time.ti_hour,dos_time.ti_min,dos_time.ti_sec);
  821.                             /*  ^^  */
  822. #else
  823.  
  824.     static char fdate[32];
  825.     time_t t;
  826.  
  827.     t = time(NULL);
  828.     strftime(fdate,31,"%d %a %y  %H:%M:%S",localtime(&t));
  829.                             /* ^^ */
  830. #endif
  831.  
  832.     return(fdate);
  833. }
  834.  
  835.  
  836.  
  837. void _cdecl debug_print (char *string,...) {  /* Local-only messages, only
  838.                                                 displayed if debug-mode is
  839.                                                 turned on by ! argument */
  840.  
  841.     word tempbaud;
  842.     static char buffer[318];
  843.  
  844.  
  845.     va_list ap;
  846.     va_start(ap,string);
  847.     vsprintf(buffer,string,ap);
  848.     va_end(ap);
  849.     if(debug_mode) {            /* note simple method of temporarily */
  850.         tempbaud = baud;        /* shutting out remote...            */
  851.         baud = 0;
  852.         printm(buffer);
  853.         baud = tempbaud;
  854.     }
  855. }
  856.  
  857.  
  858.  
  859. int _cdecl printfm (char *string,...) {  /* Like printf() for local
  860.                                            and remote */
  861.  
  862.     static char buffer[318];
  863.     int val;
  864.     va_list ap;
  865.  
  866.  
  867.     va_start(ap,string);
  868.     val = vsprintf(buffer,string,ap);
  869.     va_end(ap);
  870.     printm(buffer);
  871.     return val;
  872. }
  873.  
  874.  
  875.  
  876. int _fastcall printm (char *text) {   /* Prints local and remote */
  877.  
  878.     char *p;
  879.     int  x;
  880.  
  881.  
  882.     mprint(text);
  883.     if(!sysopin) {
  884.         while ((p = strchr(text,'\x7')) != NULL)
  885.           memmove(p,&p[1],strlen(&p[1])+1);
  886.     }
  887.     x = ansi((char FAR *)text);
  888.     getxbbstime();
  889.     return x;
  890. }
  891.  
  892.  
  893.  
  894. void _fastcall mprint (char *text) {    /* prints remote only */
  895.  
  896.     char *p;
  897.  
  898.  
  899.     if(!baud) return;
  900.     p = text;
  901.     while(*p) {
  902.         while(!fossil(TRANSMIT,*p)) carrchk();
  903.         p++;
  904.     }
  905.     getxbbstime();
  906. }
  907.  
  908.  
  909.  
  910. /* Formatted 'printf-style' output through pd screen writer */
  911.  
  912. int _cdecl dprintf (int x,int y,char *string,...) {
  913.  
  914.     static char buffer[318];
  915.     va_list ap;
  916.  
  917.  
  918.     va_start(ap,string);
  919.     vsprintf(buffer,string,ap);
  920.     va_end(ap);
  921. #ifndef __SCREEN2ASM__
  922.     return(dputs(x,y,buffer));
  923. #else
  924.     return(dputs(x,y,(char FAR *)buffer));
  925. #endif
  926. }
  927.  
  928.  
  929.  
  930. void _fastcall print_stat (void) {     /* Print status line */
  931.  
  932.     current_color = 7 * 16;     /* reverse video */
  933.     dprintf(1,maxy,"%-31.31s \04 %31.31s\04             ",
  934.             PROGRAM_NAME,username);
  935. }
  936.  
  937.  
  938.  
  939. #ifndef __SCREEN2ASM__
  940.  
  941. /*
  942.  * uses this instead of SCREEN2.ASM if all you need direct screen writes for
  943.  * is a status line.  of course, you could extend this to include the other
  944.  * functions in SCREEN2.ASM rewritten in C, but if you need that much, go with
  945.  * the ASM code.
  946.  */
  947.  
  948. int _pascal dputs (int x,int y,char *s) {
  949.  
  950.     register char *p = s;
  951.     int c = (current_color << 8);   /* get calc out of loop */
  952.  
  953.  
  954.     if(!videomethod) {                  /* direct screen writes */
  955.         register int FAR *v;
  956.  
  957.         y--;                            /* dec to 0-based (call as 1-based, */
  958.         x--;                            /* i.e. top left of screen is 1,1)  */
  959.         v = vseg + ((y * maxx) + x++);  /* point v to right spot in vid RAM */
  960.         while(*p) {                     /* until NUL terminator... */
  961.              *v++ = (*p++ | c);         /* display string to vid RAM */
  962.         }
  963.         return (int)p - (int)s;         /* return displayed length */
  964.     }
  965.     else if(videomethod == 1) {         /* bios screen writes */
  966. #ifndef __TURBOC__
  967.         union REGS rg;
  968. #endif
  969.         int        xx,yy;
  970.  
  971.         curr_cursor(&xx,&yy);
  972.         cursor(x,y);
  973.         while(*p) {
  974. #ifndef __TURBOC__
  975.             rg.h.ah = 0x09;             /* write char w/ attrib */
  976.             rg.h.al = *p++;
  977.             rg.h.bh = 0;
  978.             rg.h.bl = (char)c;
  979.             rg.x.cx = 0;
  980.             int86(0x10,&rg,&rg);
  981. #else
  982.             _AH = 0x09;
  983.             _AL = *p++;
  984.             _BH = 0;
  985.             _BL = (char)c;
  986.             _CX = 0;
  987.             geninterrupt(0x10);
  988. #endif
  989.         }
  990.         cursor(xx,yy);
  991.         return strlen(s);
  992.     }
  993.     else {                              /* dos screen writes, no color */
  994.         int        xx,yy;               /* use only as last resort */
  995.  
  996.         curr_cursor(&xx,&yy);
  997.         cursor(x,y);
  998.         c = fprintf(stdout,s);
  999.         cursor(xx,yy);
  1000.         return c;
  1001.     }
  1002. }
  1003.  
  1004. #endif
  1005.